package com.cjx.stars.service.impl;

import cn.hutool.core.util.BooleanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cjx.stars.common.MyException;
import com.cjx.stars.common.Response;
import com.cjx.stars.common.ResponseUtils;
import com.cjx.stars.constant.MessageTypeEnum;
import com.cjx.stars.pojo.table.BlogComments;
import com.cjx.stars.pojo.table.Message;
import com.cjx.stars.pojo.table.User;
import com.cjx.stars.pojo.vo.BlogVo;
import com.cjx.stars.pojo.vo.MessageVO;
import com.cjx.stars.pojo.vo.UserVo;
import com.cjx.stars.service.BlogCommentsService;
import com.cjx.stars.service.BlogService;
import com.cjx.stars.service.MessageService;
import com.cjx.stars.mapper.MessageMapper;
import com.cjx.stars.service.UserService;
import com.cjx.stars.utils.UserHolder;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.cjx.stars.constant.FailMessage.THE_SENDER_DOES_NOT_EXIST;
import static com.cjx.stars.constant.RedisConstant.*;
import static com.cjx.stars.constant.SystemConstants.PAGE_SIZE;

/**
* @author cjx
* @description 针对表【message】的数据库操作Service实现
* @createDate 2024-04-21 16:51:18
*/
@Service
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message>
    implements MessageService{

    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    @Lazy
    private BlogService blogService;
    @Resource
    private UserService userService;
    @Resource
    @Lazy
    private BlogCommentsService blogCommentsService;

    @Override
    public Response<?> getBlog() {
        //1.获取当前用户信息
        UserVo user = UserHolder.getUser();
        //2.根据key获取博文ids
        String key = BLOG_FEED_KEY + user.getUserId();
        Set<ZSetOperations.TypedTuple<String>> typedTuples = stringRedisTemplate.opsForZSet()
                .reverseRangeByScoreWithScores(key, 0, System.currentTimeMillis(), 0, PAGE_SIZE);
        if (typedTuples == null || typedTuples.isEmpty()) {
            return ResponseUtils.success();
        }
        //3.根据博文ids查询博文并返回
        ArrayList<BlogVo> blogVOList = new ArrayList<>(typedTuples.size());
        for (ZSetOperations.TypedTuple<String> tuple : typedTuples) {
            long blogId = Long.parseLong(Objects.requireNonNull(tuple.getValue()));
            BlogVo blogVO = blogService.getBlogVoById(blogId);
            blogVOList.add(blogVO);
        }
        //4.将此id的博文收件箱数量清空
        String likeNumKey = MESSAGE_BLOG_NUM_KEY + user.getUserId();
        Boolean hasKey = stringRedisTemplate.hasKey(likeNumKey);
        if (Boolean.TRUE.equals(hasKey)) {
            stringRedisTemplate.opsForValue().set(likeNumKey, "0");
        }
        return ResponseUtils.success(blogVOList);
    }

    @Override
    public Response<?> getBlogNum() {
        //1.判断是否存在此用户待看博文数量
        String blogNumKey = MESSAGE_BLOG_NUM_KEY + UserHolder.getUser().getUserId();
        Boolean isBlogNumKey = stringRedisTemplate.hasKey(blogNumKey);
        if (BooleanUtil.isFalse(isBlogNumKey)){
            return ResponseUtils.success(0);
        }
        //2.将数量返回
        return ResponseUtils.success(stringRedisTemplate.opsForValue().get(blogNumKey));
    }

    @Override
    public Response<?> getLikeNum() {
        String likeNumKey = MESSAGE_LIKE_NUM_KEY + UserHolder.getUser().getUserId();
        Boolean isLikeNumKey = stringRedisTemplate.hasKey(likeNumKey);
        if (BooleanUtil.isFalse(isLikeNumKey)){
            return ResponseUtils.success(0);
        }
        return ResponseUtils.success(stringRedisTemplate.opsForValue().get(likeNumKey));
    }

    @Override
    public Response<?> pageLikeDetail(int currentPage) {
        String userId = UserHolder.getUser().getUserId();
        //1.分页条件查询点赞信息
        LambdaQueryWrapper<Message> messageLambdaQueryWrapper = new LambdaQueryWrapper<>();
        messageLambdaQueryWrapper.eq(Message::getToId, userId)
                .and(wp -> wp.eq(Message::getType, 0).or().eq(Message::getType, 1))
                .orderBy(true, false, Message::getCreateTime);
        Page<Message> messagePage = this.page(new Page<>(currentPage, PAGE_SIZE), messageLambdaQueryWrapper);
        if (messagePage.getSize() == 0) {
            return ResponseUtils.success(new Page<>());
        }
        Page<MessageVO> messageVoPage = new Page<>();
        BeanUtils.copyProperties(messagePage, messageVoPage);
        LambdaUpdateWrapper<Message> messageLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        //2.设置当前用户的点赞记录的是否查看设置成已查看
        messageLambdaUpdateWrapper.eq(Message::getToId, userId).eq(Message::getType, 0)
                .or().eq(Message::getType, 1).set(Message::getIsRead, 1);
        this.update(messageLambdaUpdateWrapper);
        //3.将Redis中的被点赞数量设置成0
        String likeNumKey = MESSAGE_LIKE_NUM_KEY + userId;
        Boolean hasLike = stringRedisTemplate.hasKey(likeNumKey);
        if (Boolean.TRUE.equals(hasLike)) {
            stringRedisTemplate.opsForValue().set(likeNumKey, "0");
        }
        List<MessageVO> messageVOList = messagePage.getRecords().stream().map((item) -> {
            MessageVO messageVO = new MessageVO();
            BeanUtils.copyProperties(item, messageVO);
        //4.根据点赞信息查询点赞方用户信息
            User user = userService.getById(messageVO.getFromId());
            if (user == null) {
                throw new MyException(THE_SENDER_DOES_NOT_EXIST);
            }
            UserVo userVO = new UserVo();
            BeanUtils.copyProperties(user, userVO);
            messageVO.setFromUser(userVO);
        //5.如果信息类型为评论类型则查询具体的评论信息
            if (item.getType() == MessageTypeEnum.BLOG_COMMENT_LIKE.getValue()) {
                BlogComments commentsVO = blogCommentsService.getCommentById(Long.parseLong(item.getData()));
                if (commentsVO == null) {
                    BlogComments tempCommon = new BlogComments();
                    tempCommon.setContent("该评论已被删除");
                    messageVO.setComment(tempCommon);
                } else {
                    messageVO.setComment(commentsVO);
                }
            }
        //4.如果信息类型为博文类型则查询具体的博文信息
            if (item.getType() == MessageTypeEnum.BLOG_LIKE.getValue()) {
                BlogVo blogVO = blogService.getBlogVoById(Long.parseLong(item.getData()));
                messageVO.setBlog(blogVO);
            }
            return messageVO;
        }).collect(Collectors.toList());
        messageVoPage.setRecords(messageVOList);
        return ResponseUtils.success(messageVoPage);
    }

    @Override
    public Response<?> hasNewMessage() {
        String userId = UserHolder.getUser().getUserId();
        String likeNumKey = MESSAGE_LIKE_NUM_KEY + userId;
        Boolean hasLike = stringRedisTemplate.hasKey(likeNumKey);
        if (Boolean.TRUE.equals(hasLike)) {
            String likeNum = stringRedisTemplate.opsForValue().get(likeNumKey);
            assert likeNum != null;
            if (Long.parseLong(likeNum) > 0) {
                return ResponseUtils.success(true);
            }
        }
        String blogNumKey = MESSAGE_BLOG_NUM_KEY + userId;
        Boolean hasBlog = stringRedisTemplate.hasKey(blogNumKey);
        if (Boolean.TRUE.equals(hasBlog)) {
            String blogNum = stringRedisTemplate.opsForValue().get(blogNumKey);
            assert blogNum != null;
            boolean result = Long.parseLong(blogNum) > 0;
            return ResponseUtils.success(result);
        }
        return ResponseUtils.success(false);
    }
}




